package site.jlopen.components.entity;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import com.alibaba.fastjson2.JSON;

import site.jlopen.components.entity.GraphJson.GraphJsonEdge;
import site.jlopen.components.entity.GraphJson.GraphJsonNode;

public class GraphJsonUtil {
	static String json = "{\"nodes\":[{\"shape\":\"custom-html\",\"id\":\"qgckysj-node-1\",\"data\":{\"id\":\"read_data\",\"type\":\"SecretFlow\",\"shape\":\"custom-html\",\"label\":\"读取数据\",\"desc\":null,\"ports\":[\"bottom\"],\"rootName\":\"io\"},\"position\":{\"x\":140,\"y\":90},\"ports\":{\"items\":[{\"group\":\"bottom\",\"id\":\"qgckysj-node-1-bottom-0\"}],\"groups\":{\"bottom\":{\"position\":{\"name\":\"bottom\"},\"attrs\":{\"circle\":{\"magnet\":true,\"stroke\":\"#31d0c6\",\"fill\":\"#ffffff\",\"r\":5}},\"zIndex\":1}},\"zIndex\":100000}},{\"shape\":\"custom-html\",\"id\":\"qgckysj-node-2\",\"data\":{\"id\":\"read_data\",\"type\":\"SecretFlow\",\"shape\":\"custom-html\",\"label\":\"读取数据\",\"desc\":null,\"ports\":[\"bottom\"],\"rootName\":\"io\"},\"position\":{\"x\":509,\"y\":90},\"ports\":{\"items\":[{\"group\":\"bottom\",\"id\":\"qgckysj-node-2-bottom-0\"}],\"groups\":{\"bottom\":{\"position\":{\"name\":\"bottom\"},\"attrs\":{\"circle\":{\"magnet\":true,\"stroke\":\"#31d0c6\",\"fill\":\"#ffffff\",\"r\":5}},\"zIndex\":1}},\"zIndex\":100000}},{\"shape\":\"custom-html\",\"id\":\"qgckysj-node-3\",\"data\":{\"id\":\"psi\",\"type\":\"SecretFlow\",\"shape\":\"custom-html\",\"label\":\"隐私求交\",\"desc\":null,\"ports\":[\"top\",\"top\",\"bottom\"],\"rootName\":\"data_prep\"},\"position\":{\"x\":320,\"y\":237},\"ports\":{\"items\":[{\"group\":\"top\",\"id\":\"qgckysj-node-3-top-0\"},{\"group\":\"top\",\"id\":\"qgckysj-node-3-top-1\"},{\"group\":\"bottom\",\"id\":\"qgckysj-node-3-bottom-2\"}],\"groups\":{\"top\":{\"position\":{\"name\":\"top\"},\"attrs\":{\"circle\":{\"magnet\":true,\"stroke\":\"#ff0000\",\"fill\":\"#ffffff\",\"r\":5}},\"zIndex\":1},\"bottom\":{\"position\":{\"name\":\"bottom\"},\"attrs\":{\"circle\":{\"magnet\":true,\"stroke\":\"#31d0c6\",\"fill\":\"#ffffff\",\"r\":5}},\"zIndex\":1}},\"zIndex\":100000}},{\"shape\":\"custom-html\",\"id\":\"qgckysj-node-4\",\"data\":{\"id\":\"table_statistics\",\"type\":\"SecretFlow\",\"shape\":\"custom-html\",\"label\":\"全表统计\",\"desc\":null,\"ports\":[\"top\"],\"rootName\":\"stats\"},\"position\":{\"x\":320,\"y\":398},\"ports\":{\"items\":[{\"group\":\"top\",\"id\":\"qgckysj-node-4-top-0\"}],\"groups\":{\"top\":{\"position\":{\"name\":\"top\"},\"attrs\":{\"circle\":{\"magnet\":true,\"stroke\":\"#ff0000\",\"fill\":\"#ffffff\",\"r\":5}},\"zIndex\":1}},\"zIndex\":100000}}],\"edges\":[{\"shape\":\"dag-edge\",\"id\":\"qgckysj-node-1-bottom-0_qgckysj-node-3-top-0\",\"source\":{\"cell\":\"qgckysj-node-1\",\"port\":\"qgckysj-node-1-bottom-0\"},\"target\":{\"cell\":\"qgckysj-node-3\",\"port\":\"qgckysj-node-3-top-0\"}},{\"shape\":\"dag-edge\",\"id\":\"qgckysj-node-2-bottom-0_qgckysj-node-3-top-1\",\"source\":{\"cell\":\"qgckysj-node-2\",\"port\":\"qgckysj-node-2-bottom-0\"},\"target\":{\"cell\":\"qgckysj-node-3\",\"port\":\"qgckysj-node-3-top-1\"}},{\"shape\":\"dag-edge\",\"id\":\"qgckysj-node-3-bottom-2_qgckysj-node-4-top-0\",\"source\":{\"cell\":\"qgckysj-node-3\",\"port\":\"qgckysj-node-3-bottom-2\"},\"target\":{\"cell\":\"qgckysj-node-4\",\"port\":\"qgckysj-node-4-top-0\"}}]}";
	private GraphJson graphObject;

	public GraphJsonUtil(String graphJson) {
		this.graphObject = JSON.parseObject(graphJson, GraphJson.class);
	}
	
	public static void main(String[] args) {
		List<GraphListInfo> uniqueList = new GraphJsonUtil(json).getTasks();
		System.out.println(JSON.toJSON(uniqueList));
	}
	
	public List<GraphListInfo> getTasks() {
		List<GraphListInfo> list = new ArrayList<GraphListInfo>();
		List<GraphJsonNode> firsts =  getFirstNodes();
		for (GraphJsonNode node : firsts) {
			GraphListInfo gli = new GraphListInfo();
			gli.setId(node.getId());
			gli.setCode(node.getData().getId());
			gli.setTitle(node.getData().getLabel());
			gli.setSort(1);
			List<GraphJsonNode> nexts = getNextNodes(node.getId());
			if(null != nexts && nexts.size() > 0) {
				for (GraphJsonNode next : nexts) {
					gli.addTarget(next.getId());
					gli.addTargetText(next.getData().getLabel());
				}
			}
			list.add(gli);
			List<GraphListInfo> clist = getNodesList(node.getId(), 1);
			if(null != clist && clist.size() > 0) {
				list.addAll(clist);
			}
		}
		List<GraphListInfo> uniqueList = list.stream()
                .distinct()
                .sorted(Comparator.comparingInt(GraphListInfo::getSort))
                .collect(Collectors.toList());
		return uniqueList;
	}
	
	
	public List<GraphListInfo> getNodesList(String graphId, int sort){
		List<GraphListInfo> list = new ArrayList<GraphListInfo>();
		List<GraphJsonNode> nnodes = getNextNodes(graphId);
		for (GraphJsonNode node : nnodes) {
			GraphListInfo gli = new GraphListInfo();
			gli.setId(node.getId());
			gli.setCode(node.getData().getId());
			gli.setTitle(node.getData().getLabel());
			gli.setSort(sort + 1);
			List<GraphJsonNode> pnodes = getNodesForm(node.getId());
			if(null != pnodes) { 
				for (GraphJsonNode nnode : pnodes) {
					gli.addSource(nnode.getId());
					gli.addSourceText(nnode.getData().getLabel());
				}
			}
			List<GraphJsonNode> nexts = getNextNodes(node.getId());
			if(null != nexts && nexts.size() > 0) {
				for (GraphJsonNode next : nexts) {
					gli.addTarget(next.getId());
					gli.addTargetText(next.getData().getLabel());
				}
			}
			list.add(gli);
			list.addAll(getNodesList(node.getId(), sort + 1));
		}
		return list;
	}

	public GraphJsonNode getNodeById(String graphId){
		List<GraphJsonNode> nodes = graphObject.getNodes();
		for (GraphJsonNode node : nodes) {
			if(graphId.equals(node.getId())) {
				return node;
			}
		}
		return null;
	}

	public List<GraphJsonNode> getFirstNodes(){
		List<GraphJsonNode> list = new ArrayList<GraphJson.GraphJsonNode>();
		List<GraphJsonNode> nodes = graphObject.getNodes();
		for (GraphJsonNode node : nodes) {
			boolean hasTop = false;
			for (String port : node.getData().getPorts()) {
				if("top".equals(port)) {
					hasTop = true;
					break;
				}
			}
			if(hasTop == false) {
				list.add(node);
			}
		}
		
		return list;
	}
	
	public List<GraphJsonNode> getNextNodes(String graphId){
		List<GraphJsonNode> list = new ArrayList<GraphJson.GraphJsonNode>();
		List<GraphJsonNode> nodes = graphObject.getNodes();
		List<GraphJsonEdge> edges = graphObject.getEdges();
		List<String> tnodeIds = new ArrayList<String>();
		for (GraphJsonEdge edge : edges) {
			if(graphId.equals(edge.getSource().getCell())) {
				tnodeIds.add(edge.getTarget().getCell());
			}
		}
		if(tnodeIds.size() > 0) {
			for (GraphJsonNode node : nodes) {
				for (String id : tnodeIds) {
					if(id.equals(node.getId())) {
						list.add(node);
					}
				}
			}
		}
		return list;
	}

	public List<GraphJsonNode> getParentNodes(){
		List<GraphJsonNode> list = new ArrayList<GraphJson.GraphJsonNode>();
		List<GraphJsonNode> nodes = graphObject.getNodes();
		List<GraphJsonEdge> edges = graphObject.getEdges();
		// 遍历所有节点，查找没有输入的标识
		for (GraphJsonNode node : nodes) {
			boolean hasTarget = false;
			for (GraphJsonEdge edge : edges) {
				if(node.getId().equals(edge.getTarget().getCell())) {
					hasTarget = true;
				}
			}
			if(hasTarget == false) {
				list.add(node);
			}
		}
		return list;
	}
	
	public List<GraphJsonNode> getLastNodes(){
		List<GraphJsonNode> list = new ArrayList<GraphJson.GraphJsonNode>();
		List<GraphJsonNode> nodes = graphObject.getNodes();
		for (GraphJsonNode node : nodes) {
			boolean hasBottom = false;
			for (String port : node.getData().getPorts()) {
				if("bottom".equals(port)) {
					hasBottom = true;
					break;
				}
			}
			if(hasBottom == false) {
				list.add(node);
			}
		}
		return list;
	}
	
	public List<GraphJsonNode> getNodesForm(String curGraphId){
		List<GraphJsonNode> list = new ArrayList<GraphJson.GraphJsonNode>();
		List<GraphJsonEdge> edges = graphObject.getEdges();
		for (GraphJsonEdge edge : edges) {
			if(curGraphId.equals(edge.getTarget().getCell())) {
				GraphJsonNode fnode = getNodeById(edge.getSource().getCell());
				list.add(fnode);
			}
		}
		return list;
	}
}
